<?php
/**
 * 类对象注册表
 * 
 * 可以根据类和参数构造类的对象
 * <code>
 * class X {
 * 	public $a = 1;
 * 	
 * 	function X($a, $b) {
 * 		var_dump($a);
 * 		var_dump($b);
 * 		echo "<br/>";
 * 	}
 * 	
 * 	function setA($a) {
 * 		$this->a = $a;
 * 	}
 * }
 * 
 * $x = IRegistry::singleton()->single("X", 11, 23);
 * $x->setA(10); // $a --> 10
 * 
 * $x = IRegistry::singleton()->single("X", 11, 23); // 不会执行构造函数
 * $x->setA(100);  // $a --> 100
 * 
 * $x = IRegistry::singleton()->obj("X", 1, 2); // 新的$x，与上面的两个对象无关
 * </code>
 *
 * @version $Id$
 * @package if
 * @subpackage core
 * @since 1.0
 */
class IRegistry extends IObject {
	private $map = array();
	private static $instance;
	
	private function __construct() {
		
	}
	
	/**
	 * 取得当前类的实例
	 *
	 * @return IRegistry
	 */
	static function singleton() {
		if (!self::$instance) {
			self::$instance = new self;
		}
		return self::$instance;
	}
	
	/**
	 * 取得类的单例
	 * 
	 * 对于同一个类来说，多次调用该方法只返回同一个对象
	 *
	 * @param string $class 类名称
	 * @param mixed $arguments 参数列表
	 * @return object
	 */
	function single($class, $arguments = null) {
		if (gettype($class) != "string") {
			return;
		}
		if (!array_key_exists($class, $this->map)) {
			$className = if_class_name($class);
			if (!class_exists($className, false)) {
				import($class);
				if (array_key_exists($class, $this->map)) { // 二次检查，防止$class定义文件中调用了getSingleton
					return $this->map[$class];
				}
			}
			if (!class_exists($className, false)) {
				throw new IException("can not load class '{$class}' from class-path '" . implode(", ", IVM::singleton()->classPaths()) . "'", 0x100012);
			}
			
			$reflection = new ReflectionClass($className);
			if (!$reflection->getConstructor()) {
				$this->map[$class] = $reflection->newInstance();
			} else {
				$args = func_get_args();
				array_shift($args);
				$this->map[$class] = $reflection->newInstanceArgs($args);
			}
		}
		return $this->map[$class];
	}
	
	/**
	 * 取得类的实例对象
	 *
	 * @param string $class 类名称
	 * @param mixed $arguments 参数列表
	 * @return object
	 */
	function &obj($class, $arguments = null) {
		import($class);
		$className = if_class_name($class);
		$reflection = new ReflectionClass($className);
		if (!$reflection->getConstructor()) {
			$object = $reflection->newInstance();
		} else {
			$args = func_get_args();
			array_shift($args);
			$object = $reflection->newInstanceArgs($args);
		}
		$this->map[$class] = $object;
		return $object;
	}
	
	/**
	 * 添加对象引用
	 *
	 * @param IObject $object
	 * @return string
	 * @since 1.0
	 */
	function addRef(IObject $object) {
		$refId = $object->_refId();
		$this->map[$refId] = $object;
		return $refId;
	}
	
	/**
	 * 取得引用
	 *
	 * @param string $refId 引用ID
	 * @return IObject
	 * @since 1.0
	 */
	function ref($refId) {
		if (array_key_exists($refId, $this->map)) {
			return $this->map[$refId];
		}
		return null;
	}
}

?>